#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Version: Python 2.6.6
# Author: Sergey K.
# Created: 2011-08-16


import unittest

import rs
import rs.resource

@rs.get
class Class(object): pass


@rs.get
@rs.path('root')
class Tree(object):
    @rs.path('level1')
    class Level1(object):
        @rs.delete
        @rs.path('level2')
        class Level2(object):
            @rs.path('level3')
            def level3(self): pass
        @rs.put
        @rs.path('level2')
        def level2(self): pass
    @rs.post
    @rs.path('level1')
    def level1(self): pass

@rs.path('{id}')
class List(object):
    @rs.post
    def post(self): pass
    @rs.get
    def get(self): pass

@rs.get
@rs.path('index.html')
@rs.produces('application/xml; charset="utf-8"')
def function(): pass


class ResourceBuilderTest(unittest.TestCase):

    def test_build_Class(self):
        res = rs.resource.build(Class)
        eq = self.assertEquals
        eq(0, len(res))

    def test_build_Tree(self):
        res = rs.resource.build(Tree)
        eq = self.assertEquals
        eq(3, len(res))
        level1, level2, level3 = res[0], res[1], res[2]
        eq('POST', level1.method)
        eq('/root/level1', level1.path)
        eq('^root/level1$', level1.pattern.pattern)
        eq(Tree, level1.type)
        eq(Tree.__dict__['level1'], level1.target)
        eq('PUT', level2.method)
        eq('/root/level1/level2', level2.path)
        eq('^root/level1/level2$', level2.pattern.pattern)
        eq(Tree.Level1, level2.type)
        eq(Tree.Level1.__dict__['level2'], level2.target)
        eq('DELETE', level3.method)
        eq('/root/level1/level2/level3', level3.path)
        eq('^root/level1/level2/level3$', level3.pattern.pattern)
        eq(Tree.Level1.Level2, level3.type)
        eq(Tree.Level1.Level2.__dict__['level3'], level3.target)

    def test_build_List(self):
        res = rs.resource.build(List)
        eq = self.assertEquals
        eq(2, len(res))
        get, post = res[0], res[1]
        eq('POST', post.method)
        eq('/{id}', post.path)
        eq('^(?P<id>.+)$', post.pattern.pattern)
        eq(List, post.type)
        eq(List.__dict__['post'], post.target)
        eq('GET', get.method)
        eq('/{id}', get.path)
        eq('^(?P<id>.+)$', get.pattern.pattern)
        eq(List, get.type)
        eq(List.__dict__['get'], get.target)

    def test_build_function(self):
        res = rs.resource.build(function)
        eq = self.assertEquals
        eq(1, len(res))
        r = res[0]
        eq('GET', r.method)
        eq('/index.html', r.path)
        eq('^index.html$', r.pattern.pattern)
        eq(None, r.type)
        eq(function, r.target)

    def test_build_all(self):
        res = rs.resource.build_all([Class, Tree, List, function])
        self.assertEquals(6, len(res))

    def test_create_path_parameter(self):
        cls = rs.resource.ResourceBuilder
        eq = self.assertEquals
        eq(r'(?P<id>.+)',  cls.create_path_parameter('id'))
        eq(r'(?P<id>\d+)', cls.create_path_parameter('id:\\d+'))
        eq(r'(?P<id>\d+)', cls.create_path_parameter('id : \\d+'))


class ResourceTest(unittest.TestCase):

    def test_init(self):
        res = rs.resource.Resource()
        true = self.assertTrue
        true(res.target is None)
        true(res.path is None)
        true(res.type is None)
        true(res.producer is None)
        true(res.consumer is None)
        true(res.pattern is None)


class ResourceManagerTest(unittest.TestCase):

    def test_init(self):
        import rs
        @rs.path('/res1')
        def res1(): pass
        @rs.path('/res2')
        def res2(): pass
        eq = self.assertEquals
        resources = rs.resource.ResourceManager(())
        eq(0, len(resources))
        resources = rs.resource.ResourceManager([res1, res1, res1])
        eq(1, len(resources))

    def test_get_instance(self):
        from test_request import AppData
        eq = self.assertEquals
        true = self.assertTrue
        resources = rs.resource.ResourceManager(rs.resource.build_all([AppData]))
        self.assertNotEquals(0, len(resources))
        res = next(iter(resources))
        eq(0, len(resources.instances))
        inst = resources.get_instance(res)
        true(isinstance(inst, AppData))
        eq(1, len(resources.instances))
        true(inst is resources.get_instance(res))

    def test_get_args(self):
        import rs
        @rs.get
        @rs.path('/')
        def get(a, b, c='c'): pass
        eq = self.assertEquals
        true = self.assertTrue
        resources = rs.resource.ResourceManager(rs.resource.build(get))
        self.assertNotEquals(0, len(resources))
        res = next(iter(resources))
        true(res.target is get)
        eq(0, len(resources.args))
        a, d = resources.get_args(res)
        eq(3, len(a.args))
        true('a' in a.args)
        true('b' in a.args)
        true('c' in a.args)
        eq(1, len(d))
        true('c' in d)
        eq('c', d['c'])
        a1, d1 = resources.get_args(res)
        true(a1 is a)
        true(d1 is d)

        
if __name__ == '__main__':
    unittest.main()